<?php

namespace App\Command\ResumeParsing\Service\ParsingSpecial;

use App\Command\ResumeParsing\Service\TranslateHelper;
use EchoPHP\Facades\Log;
use PhpOffice\PhpSpreadsheet;

class ParsingZhilianExcel extends ParsingSpecialExcel implements PreprocessorExcel {

    protected $titlePatternTemplate = ['range' => 'A1:B1', 'core' => 'A1', 'xfIndex' => null];

    private $translateHelper;

    private $indexPageTitleRow = [[
        '姓名', '标签名称', '应聘职位', '性别', '出生日期', '工作年限', '移动电话', '电子邮件', '目前居住地', '通讯地址',
        '户口', '现在（前）单位', '现在（前）职位', '学校名称', '专业名称', '最高学历', '期望月薪（税前）', '投递时间'
    ]];

    public function __construct($helper) {
        parent::__construct($helper);

        $this->translateHelper = new TranslateHelper();

        $this->get['id'] = $this->tagNotExist;

        $this->get['time'] = function () {
            return $this->data['个人基本信息']['投递时间'] ?? '';
        };

        $this->get['name'] = function () {
            return $this->data['个人基本信息']['姓名'] ?? '';
        };

        $this->get['sex'] = function () {
            return $this->data['个人基本信息']['性别'] ?? '';
        };

        $this->get['nation'] = $this->tagNotExist;

        $this->get['identitycard'] = function () {
            return $this->data['个人基本信息']['身份证'] ?? '';
        };

        $this->get['mobile'] = function () {
            return $this->data['个人基本信息']['联系电话'] ?? '';
        };

        $this->get['email'] = function () {
            return $this->data['个人基本信息']['E-mail'] ?? '';
        };

        $this->get['age'] = $this->tagNotExist;

        $this->get['married'] = function () {
            return $this->data['个人基本信息']['婚姻状况'] ?? '';
        };

        $this->get['politic'] = function () {
            return $this->data['个人基本信息']['政治面貌'] ?? '';
        };

        $this->get['degree'] = $this->tagNotExist;

        $this->get['industry'] = function () {
            return $this->data['求职意向']['期望从事行业'] ?? '';
        };

        $this->get['position'] = $this->tagNotExist;

        $this->get['career'] = function () {
            return $this->data['求职意向']['期望从事职业'] ?? '';
        };

        $this->get['major'] = $this->tagNotExist;

        $this->get['birthday'] = function () {
            return $this->data['个人基本信息']['出生年月'] ?? '';
        };

        $this->get['workyear'] = function () {
            return $this->preg_get('/^.+(?=工作经验)/u', $this->data['个人基本信息']['工作经验'] ?? '');
        };

        $this->get['workarea'] = function () {
            return $this->data['个人基本信息']['现居住地'] ?? '';
        };

        $this->get['expectarea'] = function () {
            return $this->data['求职意向']['期望工作地区'] ?? '';
        };

        $this->get['area'] = function () {
            return $this->data['个人基本信息']['户口'] ?? '';
        };

        $this->get['salary'] = $this->tagNotExist;

        $this->get['expectsalary'] = function () {
            $resultText = $this->data['求职意向']['期望月薪'] ?? '';
            $expectSalary = $this->func->parseSalary($resultText);
            if (count($expectSalary)) {
                $this->helper->resumeInfo['expectsalaryfrom'] = $expectSalary['monthly']['begin'];
                $this->helper->resumeInfo['expectsalaryend'] = $expectSalary['monthly']['end'];
            }
            return $resultText;
        };

        $this->get['jobterm'] = function () {
            return $this->data['求职意向']['期望工作性质'] ?? '';
        };

        $this->get['school'] = $this->tagNotExist;

        $this->get['nofocuse'] = $this->tagNotExist;

        $this->groupGetter['work'] = [];

        $this->groupGetter['work'][0] = function ($group) {
            return $group;
        };

        $this->groupGetter['work'][] = function ($row) {
            if (preg_match('/^(?<time>(?<!\d)(?:(?:19|20)?\d{2}\s*年\s*[01]?\d\s*月(?:\s*[0-3]?\d[日号])?|(?:19|20)?\d{2}\s*(?<delimiter>[\-\.\/\\\\])\s*[01]?\d(?:\k<delimiter>\s*[0-3]?\d)?)(?!\d)(?:(?:\s*[-–—\/\\\\~到至]\s*)(?<!\d)(?:至今|现在|(?(delimiter)(?:19|20)?\d{2}\s*\k<delimiter>\s*[01]?\d(?:\k<delimiter>\s*[0-3]?\d)?|(?:19|20)?\d{2}\s*年\s*[01]?\d\s*月(?:\s*[0-3]?\d[日号])?))(?!\d))?)\s*(?<company>.+?)\s*(?:[(（](?<timespan>(?:\d{1,2}年(?:\s{0,2}[01]?\d个?月)?|\d{1,2}个?月)(?:以上|\+)?)[)）])?$/u', $row, $matches)) {
                $time = $matches['time'];
                $tmp = $this->func->parseTimespan($time);
                return ['comment' => !empty($matches['timespan']) ? '工作时间：' . $matches['timespan'] : '', 'time' => $time, 'time_from' => $tmp['begin'], 'time_end' => $tmp['end'], 'company' => $matches['company']];
            }
        };

        $this->groupGetter['work'][] = function ($row) {
            if (preg_match('/^(?<duty>.*?)\s*\|\s*(?<salary>面议|保密|\d+(?:\.\d+)?\s*[kw万]?\s*元?(?:\s*[-–—~～至到]\s*(?:\d+(?:\.\d+)?\s*[kw万]?)\s*元?)?\s*[\/每].*?)(?:以上|以下)?$/u', $row, $matches)) {
                return ['duty' => $matches['duty'], 'salary' => $matches['salary']];
            }
        };

        $this->groupGetter['work'][] = function ($row) {
            if (preg_match('/^\s*(?<industry>.+?)\s*\|\s*(?<comment>企业性质：.+?)\s*$/u', $row, $matches)) {
                return ['industry' => $matches['industry'], 'comment' => $matches['comment']];
            }
            if (!empty($industryArr = $this->translateHelper->getIndustryCode($row, false, true))) {
                $result = ['industry' => array_key_first($industryArr)];
                $row = str_replace($result['industry'], '', $row);
                $row = preg_replace('/(?:\s*\|\s*){2,}/u', ' | ', $row);
                $row = trim($row, " \t\n\r\0\x0B|");
                if (!empty($row)) $result['comment'] = $row;
                return $result;
            }
        };

        $this->get['workinfo'] = function () {
            $workInfo = array_column($this->data['工作经历'] ?? [], 1);
            $workInfo = $this->groupByBoundary($workInfo, function ($row) {
                return preg_match('/^(?<time>(?<!\d)(?:(?:19|20)?\d{2}\s*年\s*[01]?\d\s*月(?:\s*[0-3]?\d[日号])?|(?:19|20)?\d{2}\s*(?<delimiter>[\-\.\/\\\\])\s*[01]?\d(?:\k<delimiter>\s*[0-3]?\d)?)(?!\d)(?:(?:\s*[-–—\/\\\\~到至]\s*)(?<!\d)(?:至今|现在|(?(delimiter)(?:19|20)?\d{2}\s*\k<delimiter>\s*[01]?\d(?:\k<delimiter>\s*[0-3]?\d)?|(?:19|20)?\d{2}\s*年\s*[01]?\d\s*月(?:\s*[0-3]?\d[日号])?))(?!\d))?)\s*(?<company>.+?)\s*(?:[(（](?<timespan>(?:\d{1,2}年(?:\s{0,2}[01]?\d个?月)?|\d{1,2}个?月)(?:以上|\+)?)[)）])?$/u', $row);
            });
            $data = [];
            foreach ($workInfo as $group) {
                $data[] = $this->groupProcess('work', $group);
            }
            return $data;
        };

        $this->groupGetter['project'] = [];

        $this->groupGetter['project'][0] = function ($group) {
            return $group;
        };

        $this->groupGetter['project'][] = function ($row) {
            if ($row[0] == '项目名称' && preg_match('/^(?<time>(?<!\d)(?:(?:19|20)?\d{2}\s*年\s*[01]?\d\s*月(?:\s*[0-3]?\d[日号])?|(?:19|20)?\d{2}\s*(?<delimiter>[\-\.\/\\\\])\s*[01]?\d(?:\k<delimiter>\s*[0-3]?\d)?)(?!\d)(?:(?:\s*[-–—\/\\\\~到至]\s*)(?<!\d)(?:至今|现在|(?(delimiter)(?:19|20)?\d{2}\s*\k<delimiter>\s*[01]?\d(?:\k<delimiter>\s*[0-3]?\d)?|(?:19|20)?\d{2}\s*年\s*[01]?\d\s*月(?:\s*[0-3]?\d[日号])?))(?!\d))?)\s*(?<project>.+?)$/u', $row[1], $matches)) {
                $time = $matches['time'];
                $tmp = $this->func->parseTimespan($time);
                return ['time' => $time, 'time_from' => $tmp['begin'], 'time_end' => $tmp['end'], 'project' => $matches['project']];
            }
        };

        $this->get['projectinfo'] = function () {
            $projectInfo = $this->data['项目经验'] ?? [];
            $projectInfo = $this->groupByBoundary($projectInfo, function ($row) {
                return $row[0] == '项目名称';
            });
            $data = [];
            foreach ($projectInfo as $group) {
                $data[] = $this->groupProcess('project', $group);
            }
            return $data;
        };

        $this->get['educationinfo'] = function () {
            $educationInfo = array_column($this->data['教育经历'] ?? [], 1);
            $data = [];
            foreach ($educationInfo as $row) {
                if (preg_match('/^(?<time>(?:(?:19|20)?\d{2}\s*年\s*[01]?\d\s*月(?:\s*[0-3]?\d[日号])?|(?:19|20)?\d{2}\s*(?<delimiter>[\-\.\/\\\\])\s*[01]?\d(?:\k<delimiter>\s*[0-3]?\d)?)(?!\d)(?:(?:\s*[-–—\/\\\\~～到至]\s*)(?<!\d)(?:至今|现在|(?(delimiter)(?:19|20)?\d{2}\s*\k<delimiter>\s*[01]?\d(?:\k<delimiter>\s*[0-3]?\d)?|(?:19|20)?\d{2}\s*年\s*[01]?\d\s*月(?:\s*[0-3]?\d[日号])?))))\s+(?<school>.+?)(?:\s+(?<major>.+?))?\s+(?<degree>.+?)(?:\s+(?<comment>.+))?$/u', $row, $matches)) {
                    $time = $matches['time'];
                    $tmp = $this->func->parseTimespan($time);
                    $data[] = ['comment' => $matches['comment'] ?? '',
                        'time' => $time,
                        'time_from' => $tmp['begin'],
                        'time_end' => $tmp['end'],
                        'school' => $matches['school'],
                        'major' => $matches['major'] ?? '',
                        'degree' => $matches['degree']
                    ];
                }
            }
            return $data;
        };

        $this->get['skillinfo'] = function () {
            $resultText = '';
            if (!empty($this->data['专业技能'])) $resultText .= implode("\r\n", array_column($this->data['专业技能'], 1));
            if (!empty($this->data['语言能力'])) $resultText .= "\r\n" . '语言能力' . "\r\n" . implode("\r\n", array_column($this->data['语言能力'], 1));
            return trim($resultText);
        };

        $this->get['awardinfo'] = $this->tagNotExist;

        $this->get['commentinfo'] = function () {
            return implode("\r\n", array_column($this->data['自我评价'] ?? [], 1));
        };

        $this->get['otherinfo'] = function () {
            $resultText = '';
            foreach (['培训经历', '证书', '在校学习情况', '在校实践经验'] as $title) {
                if (!empty($this->data[$title])) $resultText .= "\r\n" . $title . "\r\n" . implode("\r\n", array_column($this->data[$title], 1));
            }
            return trim($resultText);
        };
    }

    protected function groupFormatCallback($item) {
        if (is_array($item) && count($item) == 2) $item = $item[0] . "：" . $item[1];
        return parent::groupFormatCallback($item);
    }

    protected function matchTitleStyle() {
        if (empty($cell = $this->sheet->getCellByColumnAndRow($this->titlePattern['core'][0], $this->titlePattern['core'][1], false))) return false;
        if ($cell->getValue() != '个人基本信息') return false;
        if (empty($style = $cell->getStyle())) return false;
        if ($style->getFill()->getStartColor()->getARGB() != 'FF99CCFF') return false;
        if ($style->getFill()->getFillType() != PhpSpreadsheet\Style\Fill::FILL_SOLID) return false;
        if ($style->getFont()->getSize() != 10) return false;
        if ($style->getFont()->getName() != 'Arial') return false;
        return $cell->getXfIndex();
    }

    protected function test() {
        if (!$this->getTitlePattern()) return false;
        //if ($this->sheet->getCellByColumnAndRow(2, 1)->getValue() != '如需联系方式请下载该简历') return false;
        return true;
    }

    protected function onParsed() {
        $this->explode();
        foreach (['个人基本信息', '求职意向'] as $title) {
            $this->data[$title] = $this->pairRowData($this->data[$title]);
        }
    }

    /**
     * Excel文档预处理方法，在此方法中，直接对$workbook对象进行必要的修改。
     * @param PhpSpreadsheet\Spreadsheet $workbook 待处理的Excel文档对象
     * @return bool 若Excel格式不匹配当前指定渠道，则返回false；否则返回true。
     */
    public function preprocess(PhpSpreadsheet\Spreadsheet $workbook) {
        try {
            $indexSheet = $workbook->getSheet(0);
            if ($indexSheet->rangeToArray('A1:R1') != $this->indexPageTitleRow) return false;

            $styleChecked = false;
            for ($row = 2; $row <= $indexSheet->getHighestRow(); $row++) {
                if (empty($nameCell = $indexSheet->getCellByColumnAndRow(1, $row, false))) continue;
                if (empty($targetSheet = $this->getLinkTargetSheet($nameCell))) continue;
                if (!$styleChecked) {
                    if (!$this->canParse($targetSheet)) return false;
                    $styleChecked = true;
                }
                try {
                    $data = [
                        '姓名' => $nameCell->getValue(),
                        '联系电话' => ($cell = $indexSheet->getCellByColumnAndRow(7, $row, false)) ? $cell->getValue() : '',
                        'E-mail' => ($cell = $indexSheet->getCellByColumnAndRow(8, $row, false)) ? $cell->getValue() : '',
                    ];
                    $oldValues = $this->fillInWorksheet($data, $targetSheet, 'A2:B20', 1, 2);
                    $targetSheet->setTitle(preg_replace('/' . preg_quote($oldValues['姓名'], '/') . '/u', $data['姓名'], $targetSheet->getTitle()));
                    if ($timeCell = $indexSheet->getCellByColumnAndRow(18, $row, false)) {
                        $targetSheet->insertNewRowBefore(2);
                        $xfIndex = $targetSheet->getCellByColumnAndRow(1, 3)->getXfIndex();
                        for ($column = 1; $column <= 5; $column++) {
                            $targetSheet->getCellByColumnAndRow($column, 2)->setXfIndex($xfIndex);

                        }
                        $targetSheet->getCellByColumnAndRow(1, 2)->setValue('投递时间');
                        $targetSheet->getCellByColumnAndRow(2, 2)->setValue($timeCell->getValue());
                    }
                } catch (\Exception $e) {
                    Log::error(e_dump($e), ['row' => $row], 'cmd');
                }
            }
            $workbook->removeSheetByIndex(0);
            return true;
        } catch (\Exception $e) {
            Log::error(e_dump($e), [], 'cmd');
            return false;
        }
    }
}
